package com.zhang.sequencegenerate.manager;

import com.zhang.sequencegenerate.entity.SequenceRule;
import com.zhang.sequencegenerate.enums.ModuleEnum;
import com.zhang.sequencegenerate.exception.BizException;
import com.zhang.sequencegenerate.service.SequenceRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;

import static com.zhang.sequencegenerate.constant.SequenceRuleConstant.*;

/**
 * @Description
 * @Author Mr.Zhang
 * @Date 2025/5/24 23:46
 * @Version 1.0
 */
@Slf4j
@Component
public class VoucherIdManager {

    @Autowired
    private SequenceRuleService sequenceRuleService;
    @Autowired
    private SequenceManager sequenceManager;

    /**
     * 生成序列 ID
     * <p>
     * 根据提供的 length 决定生成多少个序列 ID
     *
     * @param moduleEnum 模块枚举
     * @param length 集合长度
     * @return List<String>
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)  // TODO 为什么要用 REQUIRES_NEW
    public List<String> generateIds(ModuleEnum moduleEnum, Long length) {
        if (moduleEnum == null ||length == null) {
            throw new BizException(200, "缺失必传参数");
        }

        return this.buildIds(moduleEnum, length);
    }

    /**
     * 构建 ID
     *
     * @param moduleEnum 模块枚举
     * @param length 集合长度
     * @return List<String>
     */
    private List<String> buildIds(ModuleEnum moduleEnum, Long length) {
        List<String> ids = new ArrayList<>();

        // 1.获取序列规则
        SequenceRule sequenceRule = sequenceRuleService.getByModuleEnum(moduleEnum);
        String rule = sequenceRule.getRule().toUpperCase();

        // 2.生成 ID 前缀
        // ID 规则为： CO[yy][mm][dd][ID000000]  则第二步会生成 CO20230501 这一串前缀
        String idPref = this.generateIdPref(rule);
        log.info("idPref -> [{}]", idPref);

        // 3.生成唯一值
        Matcher matcher = SEQUENCE.matcher(rule);
        if (matcher.find()) {
            // 如果匹配上了，获取 0 的个数  （0 的个数就意味着要生成的随机数的长度）
            int zeroLength = matcher.end() - matcher.start() - 4;

            for (int i = 0; i < length; i++) {
                Long nextSequence = sequenceManager.getNextSequence(idPref);
                ids.add(idPref + String.format("%0" + zeroLength + "d", nextSequence));
            }
        } else {
            throw new BizException(200, "序列规则配置错误");
        }
        return ids;
    }

    /**
     * 生成 ID 前缀
     * <p>
     * 获取规则中的前缀，并生成规则对应的值
     *
     * @param rule 规则
     * @return String
     */
    private String generateIdPref(String rule) {
        StringBuffer sb = new StringBuffer();

        int prefixIndex = rule.indexOf("[");
        if (prefixIndex != -1) {
            // 匹配到了 [ 则截取 [ 前的字符串
            String prefix = rule.substring(0, prefixIndex);
            sb.append(prefix);
        }

        Calendar calendar = Calendar.getInstance();
        if (rule.contains(YEAR_FULL)) {
            sb.append(calendar.get(Calendar.YEAR));
        }
        if (rule.contains(YEAR_SHOT)) {
            sb.append(calendar.get(Calendar.YEAR) % 100);
        }
        if (rule.contains(MONTH)) {
            // %02d 的目的是确保有两位，不足前面补零
            sb.append(String.format("%02d", calendar.get(Calendar.MONTH) + 1));
        }
        if (rule.contains(DAY)) {
            sb.append(String.format("%02d", calendar.get(Calendar.DATE)));
        }
        if (rule.contains(WEEK)) {
            sb.append(String.format("%02d", calendar.get(Calendar.WEEK_OF_MONTH)));
        }
        if (rule.contains(HOUR)) {
            sb.append(String.format("%02d", calendar.get(Calendar.HOUR_OF_DAY)));
        }
        return sb.toString();
    }
}
